<!doctype html>

<html>
<head>
  <link rel="shortcut icon" href="static/images/favicon.ico" type="image/x-icon">
  <title>jpeg_encoder_basic.js (Closure Library API Documentation - JavaScript)</title>
  <link rel="stylesheet" href="static/css/base.css">
  <link rel="stylesheet" href="static/css/doc.css">
  <link rel="stylesheet" href="static/css/sidetree.css">
  <link rel="stylesheet" href="static/css/prettify.css">

  <script>
     var _staticFilePath = "static/";
     var _typeTreeName = "goog";
     var _fileTreeName = "Source";
  </script>

  <script src="static/js/doc.js">
  </script>


  <meta charset="utf8">
</head>

<body onload="grokdoc.onLoad();">

<div id="header">
  <div class="g-section g-tpl-50-50 g-split">
    <div class="g-unit g-first">
      <a id="logo" href="index.html">Closure Library API Documentation</a>
    </div>

    <div class="g-unit">
      <div class="g-c">
        <strong>Go to class or file:</strong>
        <input type="text" id="ac">
      </div>
    </div>
  </div>
</div>

<div class="clear"></div>

<h2><a href="closure_third_party_closure_goog_jpeg_encoder_jpeg_encoder_basic.js.html">jpeg_encoder_basic.js</a></h2>

<pre class="prettyprint lang-js">
<a name="line1"></a>/**
<a name="line2"></a> * @license
<a name="line3"></a>  Copyright (c) 2008, Adobe Systems Incorporated
<a name="line4"></a>  All rights reserved.
<a name="line5"></a>
<a name="line6"></a>  Redistribution and use in source and binary forms, with or without
<a name="line7"></a>  modification, are permitted provided that the following conditions are
<a name="line8"></a>  met:
<a name="line9"></a>
<a name="line10"></a>  * Redistributions of source code must retain the above copyright notice,
<a name="line11"></a>    this list of conditions and the following disclaimer.
<a name="line12"></a>
<a name="line13"></a>  * Redistributions in binary form must reproduce the above copyright
<a name="line14"></a>    notice, this list of conditions and the following disclaimer in the
<a name="line15"></a>    documentation and/or other materials provided with the distribution.
<a name="line16"></a>
<a name="line17"></a>  * Neither the name of Adobe Systems Incorporated nor the names of its
<a name="line18"></a>    contributors may be used to endorse or promote products derived from
<a name="line19"></a>    this software without specific prior written permission.
<a name="line20"></a>
<a name="line21"></a>  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS
<a name="line22"></a>  IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
<a name="line23"></a>  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
<a name="line24"></a>  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
<a name="line25"></a>  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
<a name="line26"></a>  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
<a name="line27"></a>  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
<a name="line28"></a>  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
<a name="line29"></a>  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
<a name="line30"></a>  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
<a name="line31"></a>  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<a name="line32"></a>*/
<a name="line33"></a>/**
<a name="line34"></a> * @license
<a name="line35"></a>JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009
<a name="line36"></a>
<a name="line37"></a>Basic GUI blocking jpeg encoder
<a name="line38"></a>
<a name="line39"></a>v 0.9
<a name="line40"></a>*/
<a name="line41"></a>
<a name="line42"></a>/**
<a name="line43"></a> * @fileoverview This code was ported from
<a name="line44"></a> * http://www.bytestrom.eu/blog/2009/1120a_jpeg_encoder_for_javascript and
<a name="line45"></a> * modified slightly for Closure.
<a name="line46"></a> */
<a name="line47"></a>
<a name="line48"></a>goog.provide(&#39;goog.crypt.JpegEncoder&#39;);
<a name="line49"></a>
<a name="line50"></a>goog.require(&#39;goog.crypt.base64&#39;);
<a name="line51"></a>
<a name="line52"></a>/**
<a name="line53"></a> * Initializes the JpegEncoder.
<a name="line54"></a> *
<a name="line55"></a> * @constructor
<a name="line56"></a> * @param {number=} opt_quality The compression quality. Default 50.
<a name="line57"></a> */
<a name="line58"></a>goog.crypt.JpegEncoder = function(opt_quality) {
<a name="line59"></a>  var self = this;
<a name="line60"></a>  var fround = Math.round;
<a name="line61"></a>  var ffloor = Math.floor;
<a name="line62"></a>  var YTable = new Array(64);
<a name="line63"></a>  var UVTable = new Array(64);
<a name="line64"></a>  var fdtbl_Y = new Array(64);
<a name="line65"></a>  var fdtbl_UV = new Array(64);
<a name="line66"></a>  var YDC_HT;
<a name="line67"></a>  var UVDC_HT;
<a name="line68"></a>  var YAC_HT;
<a name="line69"></a>  var UVAC_HT;
<a name="line70"></a>
<a name="line71"></a>  var bitcode = new Array(65535);
<a name="line72"></a>  var category = new Array(65535);
<a name="line73"></a>  var outputfDCTQuant = new Array(64);
<a name="line74"></a>  var DU = new Array(64);
<a name="line75"></a>  var byteout = [];
<a name="line76"></a>  var bytenew = 0;
<a name="line77"></a>  var bytepos = 7;
<a name="line78"></a>
<a name="line79"></a>  var YDU = new Array(64);
<a name="line80"></a>  var UDU = new Array(64);
<a name="line81"></a>  var VDU = new Array(64);
<a name="line82"></a>  var clt = new Array(256);
<a name="line83"></a>  var RGB_YUV_TABLE = new Array(2048);
<a name="line84"></a>  var currentQuality;
<a name="line85"></a>
<a name="line86"></a>  var ZigZag = [
<a name="line87"></a>       0, 1, 5, 6,14,15,27,28,
<a name="line88"></a>       2, 4, 7,13,16,26,29,42,
<a name="line89"></a>       3, 8,12,17,25,30,41,43,
<a name="line90"></a>       9,11,18,24,31,40,44,53,
<a name="line91"></a>      10,19,23,32,39,45,52,54,
<a name="line92"></a>      20,22,33,38,46,51,55,60,
<a name="line93"></a>      21,34,37,47,50,56,59,61,
<a name="line94"></a>      35,36,48,49,57,58,62,63
<a name="line95"></a>    ];
<a name="line96"></a>
<a name="line97"></a>  var std_dc_luminance_nrcodes = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0];
<a name="line98"></a>  var std_dc_luminance_values = [0,1,2,3,4,5,6,7,8,9,10,11];
<a name="line99"></a>  var std_ac_luminance_nrcodes = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d];
<a name="line100"></a>  var std_ac_luminance_values = [
<a name="line101"></a>      0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,
<a name="line102"></a>      0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,
<a name="line103"></a>      0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
<a name="line104"></a>      0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,
<a name="line105"></a>      0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,
<a name="line106"></a>      0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
<a name="line107"></a>      0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,
<a name="line108"></a>      0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
<a name="line109"></a>      0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
<a name="line110"></a>      0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
<a name="line111"></a>      0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,
<a name="line112"></a>      0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
<a name="line113"></a>      0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,
<a name="line114"></a>      0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
<a name="line115"></a>      0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
<a name="line116"></a>      0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,
<a name="line117"></a>      0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,
<a name="line118"></a>      0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
<a name="line119"></a>      0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,
<a name="line120"></a>      0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
<a name="line121"></a>      0xf9,0xfa
<a name="line122"></a>    ];
<a name="line123"></a>
<a name="line124"></a>  var std_dc_chrominance_nrcodes = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0];
<a name="line125"></a>  var std_dc_chrominance_values = [0,1,2,3,4,5,6,7,8,9,10,11];
<a name="line126"></a>  var std_ac_chrominance_nrcodes = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77];
<a name="line127"></a>  var std_ac_chrominance_values = [
<a name="line128"></a>      0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,
<a name="line129"></a>      0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
<a name="line130"></a>      0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
<a name="line131"></a>      0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,
<a name="line132"></a>      0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,
<a name="line133"></a>      0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
<a name="line134"></a>      0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,
<a name="line135"></a>      0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,
<a name="line136"></a>      0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
<a name="line137"></a>      0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,
<a name="line138"></a>      0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,
<a name="line139"></a>      0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
<a name="line140"></a>      0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,
<a name="line141"></a>      0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,
<a name="line142"></a>      0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
<a name="line143"></a>      0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,
<a name="line144"></a>      0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,
<a name="line145"></a>      0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
<a name="line146"></a>      0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,
<a name="line147"></a>      0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
<a name="line148"></a>      0xf9,0xfa
<a name="line149"></a>    ];
<a name="line150"></a>
<a name="line151"></a>  function initQuantTables(sf){
<a name="line152"></a>      var YQT = [
<a name="line153"></a>        16, 11, 10, 16, 24, 40, 51, 61,
<a name="line154"></a>        12, 12, 14, 19, 26, 58, 60, 55,
<a name="line155"></a>        14, 13, 16, 24, 40, 57, 69, 56,
<a name="line156"></a>        14, 17, 22, 29, 51, 87, 80, 62,
<a name="line157"></a>        18, 22, 37, 56, 68,109,103, 77,
<a name="line158"></a>        24, 35, 55, 64, 81,104,113, 92,
<a name="line159"></a>        49, 64, 78, 87,103,121,120,101,
<a name="line160"></a>        72, 92, 95, 98,112,100,103, 99
<a name="line161"></a>      ];
<a name="line162"></a>
<a name="line163"></a>      for (var i = 0; i &lt; 64; i++) {
<a name="line164"></a>        var t = ffloor((YQT[i]*sf+50)/100);
<a name="line165"></a>        if (t &lt; 1) {
<a name="line166"></a>          t = 1;
<a name="line167"></a>        } else if (t &gt; 255) {
<a name="line168"></a>          t = 255;
<a name="line169"></a>        }
<a name="line170"></a>        YTable[ZigZag[i]] = t;
<a name="line171"></a>      }
<a name="line172"></a>      var UVQT = [
<a name="line173"></a>        17, 18, 24, 47, 99, 99, 99, 99,
<a name="line174"></a>        18, 21, 26, 66, 99, 99, 99, 99,
<a name="line175"></a>        24, 26, 56, 99, 99, 99, 99, 99,
<a name="line176"></a>        47, 66, 99, 99, 99, 99, 99, 99,
<a name="line177"></a>        99, 99, 99, 99, 99, 99, 99, 99,
<a name="line178"></a>        99, 99, 99, 99, 99, 99, 99, 99,
<a name="line179"></a>        99, 99, 99, 99, 99, 99, 99, 99,
<a name="line180"></a>        99, 99, 99, 99, 99, 99, 99, 99
<a name="line181"></a>      ];
<a name="line182"></a>      for (var j = 0; j &lt; 64; j++) {
<a name="line183"></a>        var u = ffloor((UVQT[j]*sf+50)/100);
<a name="line184"></a>        if (u &lt; 1) {
<a name="line185"></a>          u = 1;
<a name="line186"></a>        } else if (u &gt; 255) {
<a name="line187"></a>          u = 255;
<a name="line188"></a>        }
<a name="line189"></a>        UVTable[ZigZag[j]] = u;
<a name="line190"></a>      }
<a name="line191"></a>      var aasf = [
<a name="line192"></a>        1.0, 1.387039845, 1.306562965, 1.175875602,
<a name="line193"></a>        1.0, 0.785694958, 0.541196100, 0.275899379
<a name="line194"></a>      ];
<a name="line195"></a>      var k = 0;
<a name="line196"></a>      for (var row = 0; row &lt; 8; row++)
<a name="line197"></a>      {
<a name="line198"></a>        for (var col = 0; col &lt; 8; col++)
<a name="line199"></a>        {
<a name="line200"></a>          fdtbl_Y[k]  = (1.0 / (YTable [ZigZag[k]] * aasf[row] * aasf[col] * 8.0));
<a name="line201"></a>          fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0));
<a name="line202"></a>          k++;
<a name="line203"></a>        }
<a name="line204"></a>      }
<a name="line205"></a>    }
<a name="line206"></a>
<a name="line207"></a>    function computeHuffmanTbl(nrcodes, std_table){
<a name="line208"></a>      var codevalue = 0;
<a name="line209"></a>      var pos_in_table = 0;
<a name="line210"></a>      var HT = new Array();
<a name="line211"></a>      for (var k = 1; k &lt;= 16; k++) {
<a name="line212"></a>        for (var j = 1; j &lt;= nrcodes[k]; j++) {
<a name="line213"></a>          HT[std_table[pos_in_table]] = [];
<a name="line214"></a>          HT[std_table[pos_in_table]][0] = codevalue;
<a name="line215"></a>          HT[std_table[pos_in_table]][1] = k;
<a name="line216"></a>          pos_in_table++;
<a name="line217"></a>          codevalue++;
<a name="line218"></a>        }
<a name="line219"></a>        codevalue*=2;
<a name="line220"></a>      }
<a name="line221"></a>      return HT;
<a name="line222"></a>    }
<a name="line223"></a>
<a name="line224"></a>    function initHuffmanTbl()
<a name="line225"></a>    {
<a name="line226"></a>      YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values);
<a name="line227"></a>      UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values);
<a name="line228"></a>      YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values);
<a name="line229"></a>      UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values);
<a name="line230"></a>    }
<a name="line231"></a>
<a name="line232"></a>    function initCategoryNumber()
<a name="line233"></a>    {
<a name="line234"></a>      var nrlower = 1;
<a name="line235"></a>      var nrupper = 2;
<a name="line236"></a>      for (var cat = 1; cat &lt;= 15; cat++) {
<a name="line237"></a>        //Positive numbers
<a name="line238"></a>        for (var nr = nrlower; nr&lt;nrupper; nr++) {
<a name="line239"></a>          category[32767+nr] = cat;
<a name="line240"></a>          bitcode[32767+nr] = [];
<a name="line241"></a>          bitcode[32767+nr][1] = cat;
<a name="line242"></a>          bitcode[32767+nr][0] = nr;
<a name="line243"></a>        }
<a name="line244"></a>        //Negative numbers
<a name="line245"></a>        for (var nrneg =-(nrupper-1); nrneg&lt;=-nrlower; nrneg++) {
<a name="line246"></a>          category[32767+nrneg] = cat;
<a name="line247"></a>          bitcode[32767+nrneg] = [];
<a name="line248"></a>          bitcode[32767+nrneg][1] = cat;
<a name="line249"></a>          bitcode[32767+nrneg][0] = nrupper-1+nrneg;
<a name="line250"></a>        }
<a name="line251"></a>        nrlower &lt;&lt;= 1;
<a name="line252"></a>        nrupper &lt;&lt;= 1;
<a name="line253"></a>      }
<a name="line254"></a>    }
<a name="line255"></a>
<a name="line256"></a>    function initRGBYUVTable() {
<a name="line257"></a>      for(var i = 0; i &lt; 256;i++) {
<a name="line258"></a>        RGB_YUV_TABLE[i]          =  19595 * i;
<a name="line259"></a>        RGB_YUV_TABLE[(i+ 256)&gt;&gt;0]   =  38470 * i;
<a name="line260"></a>        RGB_YUV_TABLE[(i+ 512)&gt;&gt;0]   =   7471 * i + 0x8000;
<a name="line261"></a>        RGB_YUV_TABLE[(i+ 768)&gt;&gt;0]   = -11059 * i;
<a name="line262"></a>        RGB_YUV_TABLE[(i+1024)&gt;&gt;0]   = -21709 * i;
<a name="line263"></a>        RGB_YUV_TABLE[(i+1280)&gt;&gt;0]   =  32768 * i + 0x807FFF;
<a name="line264"></a>        RGB_YUV_TABLE[(i+1536)&gt;&gt;0]   = -27439 * i;
<a name="line265"></a>        RGB_YUV_TABLE[(i+1792)&gt;&gt;0]   = - 5329 * i;
<a name="line266"></a>      }
<a name="line267"></a>    }
<a name="line268"></a>
<a name="line269"></a>    // IO functions
<a name="line270"></a>    function writeBits(bs)
<a name="line271"></a>    {
<a name="line272"></a>      var value = bs[0];
<a name="line273"></a>      var posval = bs[1]-1;
<a name="line274"></a>      while ( posval &gt;= 0 ) {
<a name="line275"></a>        if (value &amp; (1 &lt;&lt; posval) ) {
<a name="line276"></a>          bytenew |= (1 &lt;&lt; bytepos);
<a name="line277"></a>        }
<a name="line278"></a>        posval--;
<a name="line279"></a>        bytepos--;
<a name="line280"></a>        if (bytepos &lt; 0) {
<a name="line281"></a>          if (bytenew == 0xFF) {
<a name="line282"></a>            writeByte(0xFF);
<a name="line283"></a>            writeByte(0);
<a name="line284"></a>          }
<a name="line285"></a>          else {
<a name="line286"></a>            writeByte(bytenew);
<a name="line287"></a>          }
<a name="line288"></a>          bytepos=7;
<a name="line289"></a>          bytenew=0;
<a name="line290"></a>        }
<a name="line291"></a>      }
<a name="line292"></a>    }
<a name="line293"></a>
<a name="line294"></a>    function writeByte(value)
<a name="line295"></a>    {
<a name="line296"></a>      byteout.push(clt[value]); // write char directly instead of converting later
<a name="line297"></a>    }
<a name="line298"></a>
<a name="line299"></a>    function writeWord(value)
<a name="line300"></a>    {
<a name="line301"></a>      writeByte((value&gt;&gt;8)&amp;0xFF);
<a name="line302"></a>      writeByte((value   )&amp;0xFF);
<a name="line303"></a>    }
<a name="line304"></a>
<a name="line305"></a>    // DCT &amp; quantization core
<a name="line306"></a>    function fDCTQuant(data, fdtbl)
<a name="line307"></a>    {
<a name="line308"></a>      var d0, d1, d2, d3, d4, d5, d6, d7;
<a name="line309"></a>      /* Pass 1: process rows. */
<a name="line310"></a>      var dataOff=0;
<a name="line311"></a>      var i;
<a name="line312"></a>      var I8 = 8;
<a name="line313"></a>      var I64 = 64;
<a name="line314"></a>      for (i=0; i&lt;I8; ++i)
<a name="line315"></a>      {
<a name="line316"></a>        d0 = data[dataOff];
<a name="line317"></a>        d1 = data[dataOff+1];
<a name="line318"></a>        d2 = data[dataOff+2];
<a name="line319"></a>        d3 = data[dataOff+3];
<a name="line320"></a>        d4 = data[dataOff+4];
<a name="line321"></a>        d5 = data[dataOff+5];
<a name="line322"></a>        d6 = data[dataOff+6];
<a name="line323"></a>        d7 = data[dataOff+7];
<a name="line324"></a>
<a name="line325"></a>        var tmp0 = d0 + d7;
<a name="line326"></a>        var tmp7 = d0 - d7;
<a name="line327"></a>        var tmp1 = d1 + d6;
<a name="line328"></a>        var tmp6 = d1 - d6;
<a name="line329"></a>        var tmp2 = d2 + d5;
<a name="line330"></a>        var tmp5 = d2 - d5;
<a name="line331"></a>        var tmp3 = d3 + d4;
<a name="line332"></a>        var tmp4 = d3 - d4;
<a name="line333"></a>
<a name="line334"></a>        /* Even part */
<a name="line335"></a>        var tmp10 = tmp0 + tmp3;  /* phase 2 */
<a name="line336"></a>        var tmp13 = tmp0 - tmp3;
<a name="line337"></a>        var tmp11 = tmp1 + tmp2;
<a name="line338"></a>        var tmp12 = tmp1 - tmp2;
<a name="line339"></a>
<a name="line340"></a>        data[dataOff] = tmp10 + tmp11; /* phase 3 */
<a name="line341"></a>        data[dataOff+4] = tmp10 - tmp11;
<a name="line342"></a>
<a name="line343"></a>        var z1 = (tmp12 + tmp13) * 0.707106781; /* c4 */
<a name="line344"></a>        data[dataOff+2] = tmp13 + z1; /* phase 5 */
<a name="line345"></a>        data[dataOff+6] = tmp13 - z1;
<a name="line346"></a>
<a name="line347"></a>        /* Odd part */
<a name="line348"></a>        tmp10 = tmp4 + tmp5; /* phase 2 */
<a name="line349"></a>        tmp11 = tmp5 + tmp6;
<a name="line350"></a>        tmp12 = tmp6 + tmp7;
<a name="line351"></a>
<a name="line352"></a>        /* The rotator is modified from fig 4-8 to avoid extra negations. */
<a name="line353"></a>        var z5 = (tmp10 - tmp12) * 0.382683433; /* c6 */
<a name="line354"></a>        var z2 = 0.541196100 * tmp10 + z5; /* c2-c6 */
<a name="line355"></a>        var z4 = 1.306562965 * tmp12 + z5; /* c2+c6 */
<a name="line356"></a>        var z3 = tmp11 * 0.707106781; /* c4 */
<a name="line357"></a>
<a name="line358"></a>        var z11 = tmp7 + z3;  /* phase 5 */
<a name="line359"></a>        var z13 = tmp7 - z3;
<a name="line360"></a>
<a name="line361"></a>        data[dataOff+5] = z13 + z2;  /* phase 6 */
<a name="line362"></a>        data[dataOff+3] = z13 - z2;
<a name="line363"></a>        data[dataOff+1] = z11 + z4;
<a name="line364"></a>        data[dataOff+7] = z11 - z4;
<a name="line365"></a>
<a name="line366"></a>        dataOff += 8; /* advance pointer to next row */
<a name="line367"></a>      }
<a name="line368"></a>
<a name="line369"></a>      /* Pass 2: process columns. */
<a name="line370"></a>      dataOff = 0;
<a name="line371"></a>      for (i=0; i&lt;I8; ++i)
<a name="line372"></a>      {
<a name="line373"></a>        d0 = data[dataOff];
<a name="line374"></a>        d1 = data[dataOff + 8];
<a name="line375"></a>        d2 = data[dataOff + 16];
<a name="line376"></a>        d3 = data[dataOff + 24];
<a name="line377"></a>        d4 = data[dataOff + 32];
<a name="line378"></a>        d5 = data[dataOff + 40];
<a name="line379"></a>        d6 = data[dataOff + 48];
<a name="line380"></a>        d7 = data[dataOff + 56];
<a name="line381"></a>
<a name="line382"></a>        var tmp0p2 = d0 + d7;
<a name="line383"></a>        var tmp7p2 = d0 - d7;
<a name="line384"></a>        var tmp1p2 = d1 + d6;
<a name="line385"></a>        var tmp6p2 = d1 - d6;
<a name="line386"></a>        var tmp2p2 = d2 + d5;
<a name="line387"></a>        var tmp5p2 = d2 - d5;
<a name="line388"></a>        var tmp3p2 = d3 + d4;
<a name="line389"></a>        var tmp4p2 = d3 - d4;
<a name="line390"></a>
<a name="line391"></a>        /* Even part */
<a name="line392"></a>        var tmp10p2 = tmp0p2 + tmp3p2;  /* phase 2 */
<a name="line393"></a>        var tmp13p2 = tmp0p2 - tmp3p2;
<a name="line394"></a>        var tmp11p2 = tmp1p2 + tmp2p2;
<a name="line395"></a>        var tmp12p2 = tmp1p2 - tmp2p2;
<a name="line396"></a>
<a name="line397"></a>        data[dataOff] = tmp10p2 + tmp11p2; /* phase 3 */
<a name="line398"></a>        data[dataOff+32] = tmp10p2 - tmp11p2;
<a name="line399"></a>
<a name="line400"></a>        var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781; /* c4 */
<a name="line401"></a>        data[dataOff+16] = tmp13p2 + z1p2; /* phase 5 */
<a name="line402"></a>        data[dataOff+48] = tmp13p2 - z1p2;
<a name="line403"></a>
<a name="line404"></a>        /* Odd part */
<a name="line405"></a>        tmp10p2 = tmp4p2 + tmp5p2; /* phase 2 */
<a name="line406"></a>        tmp11p2 = tmp5p2 + tmp6p2;
<a name="line407"></a>        tmp12p2 = tmp6p2 + tmp7p2;
<a name="line408"></a>
<a name="line409"></a>        /* The rotator is modified from fig 4-8 to avoid extra negations. */
<a name="line410"></a>        var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433; /* c6 */
<a name="line411"></a>        var z2p2 = 0.541196100 * tmp10p2 + z5p2; /* c2-c6 */
<a name="line412"></a>        var z4p2 = 1.306562965 * tmp12p2 + z5p2; /* c2+c6 */
<a name="line413"></a>        var z3p2 = tmp11p2 * 0.707106781; /* c4 */
<a name="line414"></a>
<a name="line415"></a>        var z11p2 = tmp7p2 + z3p2;  /* phase 5 */
<a name="line416"></a>        var z13p2 = tmp7p2 - z3p2;
<a name="line417"></a>
<a name="line418"></a>        data[dataOff+40] = z13p2 + z2p2; /* phase 6 */
<a name="line419"></a>        data[dataOff+24] = z13p2 - z2p2;
<a name="line420"></a>        data[dataOff+ 8] = z11p2 + z4p2;
<a name="line421"></a>        data[dataOff+56] = z11p2 - z4p2;
<a name="line422"></a>
<a name="line423"></a>        dataOff++; /* advance pointer to next column */
<a name="line424"></a>      }
<a name="line425"></a>
<a name="line426"></a>      // Quantize/descale the coefficients
<a name="line427"></a>      var fDCTQuant;
<a name="line428"></a>      for (i=0; i&lt;I64; ++i)
<a name="line429"></a>      {
<a name="line430"></a>        // Apply the quantization and scaling factor &amp; Round to nearest integer
<a name="line431"></a>        fDCTQuant = data[i]*fdtbl[i];
<a name="line432"></a>        outputfDCTQuant[i] = (fDCTQuant &gt; 0.0) ? ((fDCTQuant + 0.5)|0) : ((fDCTQuant - 0.5)|0);
<a name="line433"></a>        //outputfDCTQuant[i] = fround(fDCTQuant);
<a name="line434"></a>
<a name="line435"></a>      }
<a name="line436"></a>      return outputfDCTQuant;
<a name="line437"></a>    }
<a name="line438"></a>
<a name="line439"></a>    function writeAPP0()
<a name="line440"></a>    {
<a name="line441"></a>      writeWord(0xFFE0); // marker
<a name="line442"></a>      writeWord(16); // length
<a name="line443"></a>      writeByte(0x4A); // J
<a name="line444"></a>      writeByte(0x46); // F
<a name="line445"></a>      writeByte(0x49); // I
<a name="line446"></a>      writeByte(0x46); // F
<a name="line447"></a>      writeByte(0); // = &quot;JFIF&quot;,&#39;\0&#39;
<a name="line448"></a>      writeByte(1); // versionhi
<a name="line449"></a>      writeByte(1); // versionlo
<a name="line450"></a>      writeByte(0); // xyunits
<a name="line451"></a>      writeWord(1); // xdensity
<a name="line452"></a>      writeWord(1); // ydensity
<a name="line453"></a>      writeByte(0); // thumbnwidth
<a name="line454"></a>      writeByte(0); // thumbnheight
<a name="line455"></a>    }
<a name="line456"></a>
<a name="line457"></a>    function writeSOF0(width, height)
<a name="line458"></a>    {
<a name="line459"></a>      writeWord(0xFFC0); // marker
<a name="line460"></a>      writeWord(17);   // length, truecolor YUV JPG
<a name="line461"></a>      writeByte(8);    // precision
<a name="line462"></a>      writeWord(height);
<a name="line463"></a>      writeWord(width);
<a name="line464"></a>      writeByte(3);    // nrofcomponents
<a name="line465"></a>      writeByte(1);    // IdY
<a name="line466"></a>      writeByte(0x11); // HVY
<a name="line467"></a>      writeByte(0);    // QTY
<a name="line468"></a>      writeByte(2);    // IdU
<a name="line469"></a>      writeByte(0x11); // HVU
<a name="line470"></a>      writeByte(1);    // QTU
<a name="line471"></a>      writeByte(3);    // IdV
<a name="line472"></a>      writeByte(0x11); // HVV
<a name="line473"></a>      writeByte(1);    // QTV
<a name="line474"></a>    }
<a name="line475"></a>
<a name="line476"></a>    function writeDQT()
<a name="line477"></a>    {
<a name="line478"></a>      writeWord(0xFFDB); // marker
<a name="line479"></a>      writeWord(132);     // length
<a name="line480"></a>      writeByte(0);
<a name="line481"></a>      for (var i=0; i&lt;64; i++) {
<a name="line482"></a>        writeByte(YTable[i]);
<a name="line483"></a>      }
<a name="line484"></a>      writeByte(1);
<a name="line485"></a>      for (var j=0; j&lt;64; j++) {
<a name="line486"></a>        writeByte(UVTable[j]);
<a name="line487"></a>      }
<a name="line488"></a>    }
<a name="line489"></a>
<a name="line490"></a>    function writeDHT()
<a name="line491"></a>    {
<a name="line492"></a>      writeWord(0xFFC4); // marker
<a name="line493"></a>      writeWord(0x01A2); // length
<a name="line494"></a>
<a name="line495"></a>      writeByte(0); // HTYDCinfo
<a name="line496"></a>      for (var i=0; i&lt;16; i++) {
<a name="line497"></a>        writeByte(std_dc_luminance_nrcodes[i+1]);
<a name="line498"></a>      }
<a name="line499"></a>      for (var j=0; j&lt;=11; j++) {
<a name="line500"></a>        writeByte(std_dc_luminance_values[j]);
<a name="line501"></a>      }
<a name="line502"></a>
<a name="line503"></a>      writeByte(0x10); // HTYACinfo
<a name="line504"></a>      for (var k=0; k&lt;16; k++) {
<a name="line505"></a>        writeByte(std_ac_luminance_nrcodes[k+1]);
<a name="line506"></a>      }
<a name="line507"></a>      for (var l=0; l&lt;=161; l++) {
<a name="line508"></a>        writeByte(std_ac_luminance_values[l]);
<a name="line509"></a>      }
<a name="line510"></a>
<a name="line511"></a>      writeByte(1); // HTUDCinfo
<a name="line512"></a>      for (var m=0; m&lt;16; m++) {
<a name="line513"></a>        writeByte(std_dc_chrominance_nrcodes[m+1]);
<a name="line514"></a>      }
<a name="line515"></a>      for (var n=0; n&lt;=11; n++) {
<a name="line516"></a>        writeByte(std_dc_chrominance_values[n]);
<a name="line517"></a>      }
<a name="line518"></a>
<a name="line519"></a>      writeByte(0x11); // HTUACinfo
<a name="line520"></a>      for (var o=0; o&lt;16; o++) {
<a name="line521"></a>        writeByte(std_ac_chrominance_nrcodes[o+1]);
<a name="line522"></a>      }
<a name="line523"></a>      for (var p=0; p&lt;=161; p++) {
<a name="line524"></a>        writeByte(std_ac_chrominance_values[p]);
<a name="line525"></a>      }
<a name="line526"></a>    }
<a name="line527"></a>
<a name="line528"></a>    function writeSOS()
<a name="line529"></a>    {
<a name="line530"></a>      writeWord(0xFFDA); // marker
<a name="line531"></a>      writeWord(12); // length
<a name="line532"></a>      writeByte(3); // nrofcomponents
<a name="line533"></a>      writeByte(1); // IdY
<a name="line534"></a>      writeByte(0); // HTY
<a name="line535"></a>      writeByte(2); // IdU
<a name="line536"></a>      writeByte(0x11); // HTU
<a name="line537"></a>      writeByte(3); // IdV
<a name="line538"></a>      writeByte(0x11); // HTV
<a name="line539"></a>      writeByte(0); // Ss
<a name="line540"></a>      writeByte(0x3f); // Se
<a name="line541"></a>      writeByte(0); // Bf
<a name="line542"></a>    }
<a name="line543"></a>
<a name="line544"></a>    function processDU(CDU, fdtbl, DC, HTDC, HTAC){
<a name="line545"></a>      var EOB = HTAC[0x00];
<a name="line546"></a>      var M16zeroes = HTAC[0xF0];
<a name="line547"></a>      var pos;
<a name="line548"></a>      var I16 = 16;
<a name="line549"></a>      var I63 = 63;
<a name="line550"></a>      var I64 = 64;
<a name="line551"></a>      var DU_DCT = fDCTQuant(CDU, fdtbl);
<a name="line552"></a>      //ZigZag reorder
<a name="line553"></a>      for (var j=0;j&lt;I64;++j) {
<a name="line554"></a>        DU[ZigZag[j]]=DU_DCT[j];
<a name="line555"></a>      }
<a name="line556"></a>      var Diff = DU[0] - DC; DC = DU[0];
<a name="line557"></a>      //Encode DC
<a name="line558"></a>      if (Diff==0) {
<a name="line559"></a>        writeBits(HTDC[0]); // Diff might be 0
<a name="line560"></a>      } else {
<a name="line561"></a>        pos = 32767+Diff;
<a name="line562"></a>        writeBits(HTDC[category[pos]]);
<a name="line563"></a>        writeBits(bitcode[pos]);
<a name="line564"></a>      }
<a name="line565"></a>      //Encode ACs
<a name="line566"></a>      var end0pos = 63; // was const... which is crazy
<a name="line567"></a>      for (; (end0pos&gt;0)&amp;&amp;(DU[end0pos]==0); end0pos--) {};
<a name="line568"></a>      //end0pos = first element in reverse order !=0
<a name="line569"></a>      if ( end0pos == 0) {
<a name="line570"></a>        writeBits(EOB);
<a name="line571"></a>        return DC;
<a name="line572"></a>      }
<a name="line573"></a>      var i = 1;
<a name="line574"></a>      var lng;
<a name="line575"></a>      while ( i &lt;= end0pos ) {
<a name="line576"></a>        var startpos = i;
<a name="line577"></a>        for (; (DU[i]==0) &amp;&amp; (i&lt;=end0pos); ++i) {}
<a name="line578"></a>        var nrzeroes = i-startpos;
<a name="line579"></a>        if ( nrzeroes &gt;= I16 ) {
<a name="line580"></a>          lng = nrzeroes&gt;&gt;4;
<a name="line581"></a>          for (var nrmarker=1; nrmarker &lt;= lng; ++nrmarker)
<a name="line582"></a>            writeBits(M16zeroes);
<a name="line583"></a>          nrzeroes = nrzeroes&amp;0xF;
<a name="line584"></a>        }
<a name="line585"></a>        pos = 32767+DU[i];
<a name="line586"></a>        writeBits(HTAC[(nrzeroes&lt;&lt;4)+category[pos]]);
<a name="line587"></a>        writeBits(bitcode[pos]);
<a name="line588"></a>        i++;
<a name="line589"></a>      }
<a name="line590"></a>      if ( end0pos != I63 ) {
<a name="line591"></a>        writeBits(EOB);
<a name="line592"></a>      }
<a name="line593"></a>      return DC;
<a name="line594"></a>    }
<a name="line595"></a>
<a name="line596"></a>    function initCharLookupTable(){
<a name="line597"></a>      var sfcc = String.fromCharCode;
<a name="line598"></a>      for(var i=0; i &lt; 256; i++){ ///// ACHTUNG // 255
<a name="line599"></a>        clt[i] = sfcc(i);
<a name="line600"></a>      }
<a name="line601"></a>    }
<a name="line602"></a>
<a name="line603"></a>/**
<a name="line604"></a> * Encodes ImageData to JPEG.
<a name="line605"></a> *
<a name="line606"></a> * @param {ImageData} image
<a name="line607"></a> * @param {number=} opt_quality The compression quality.
<a name="line608"></a> * @return {string} base64-encoded JPEG data.
<a name="line609"></a> */
<a name="line610"></a>    this.encode = function(image,opt_quality) // image data object
<a name="line611"></a>    {
<a name="line612"></a>      if(opt_quality) setQuality(opt_quality);
<a name="line613"></a>
<a name="line614"></a>      // Initialize bit writer
<a name="line615"></a>      byteout = new Array();
<a name="line616"></a>      bytenew=0;
<a name="line617"></a>      bytepos=7;
<a name="line618"></a>
<a name="line619"></a>      // Add JPEG headers
<a name="line620"></a>      writeWord(0xFFD8); // SOI
<a name="line621"></a>      writeAPP0();
<a name="line622"></a>      writeDQT();
<a name="line623"></a>      writeSOF0(image.width,image.height);
<a name="line624"></a>      writeDHT();
<a name="line625"></a>      writeSOS();
<a name="line626"></a>
<a name="line627"></a>
<a name="line628"></a>      // Encode 8x8 macroblocks
<a name="line629"></a>      var _DCY=0;
<a name="line630"></a>      var _DCU=0;
<a name="line631"></a>      var _DCV=0;
<a name="line632"></a>
<a name="line633"></a>      bytenew=0;
<a name="line634"></a>      bytepos=7;
<a name="line635"></a>
<a name="line636"></a>
<a name="line637"></a>      this.encode.displayName = &quot;_encode_&quot;;
<a name="line638"></a>
<a name="line639"></a>      var imageData = image.data;
<a name="line640"></a>      var width = image.width;
<a name="line641"></a>      var height = image.height;
<a name="line642"></a>
<a name="line643"></a>      var quadWidth = width*4;
<a name="line644"></a>      var tripleWidth = width*3;
<a name="line645"></a>
<a name="line646"></a>      var x, y = 0;
<a name="line647"></a>      var r, g, b;
<a name="line648"></a>      var start,p, col,row,pos;
<a name="line649"></a>      while(y &lt; height){
<a name="line650"></a>        x = 0;
<a name="line651"></a>        while(x &lt; quadWidth){
<a name="line652"></a>        start = quadWidth * y + x;
<a name="line653"></a>        p = start;
<a name="line654"></a>        col = -1;
<a name="line655"></a>        row = 0;
<a name="line656"></a>
<a name="line657"></a>        for(pos=0; pos &lt; 64; pos++){
<a name="line658"></a>          row = pos &gt;&gt; 3;// /8
<a name="line659"></a>          col = ( pos &amp; 7 ) * 4; // %8
<a name="line660"></a>          p = start + ( row * quadWidth ) + col;
<a name="line661"></a>
<a name="line662"></a>          if(y+row &gt;= height){ // padding bottom
<a name="line663"></a>            p-= (quadWidth*(y+1+row-height));
<a name="line664"></a>          }
<a name="line665"></a>
<a name="line666"></a>          if(x+col &gt;= quadWidth){ // padding right
<a name="line667"></a>            p-= ((x+col) - quadWidth +4)
<a name="line668"></a>          }
<a name="line669"></a>
<a name="line670"></a>          r = imageData[ p++ ];
<a name="line671"></a>          g = imageData[ p++ ];
<a name="line672"></a>          b = imageData[ p++ ];
<a name="line673"></a>
<a name="line674"></a>
<a name="line675"></a>          /* // calculate YUV values dynamically
<a name="line676"></a>          YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80
<a name="line677"></a>          UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b));
<a name="line678"></a>          VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b));
<a name="line679"></a>          */
<a name="line680"></a>
<a name="line681"></a>          // use lookup table (slightly faster)
<a name="line682"></a>          YDU[pos] = ((RGB_YUV_TABLE[r]             + RGB_YUV_TABLE[(g +  256)&gt;&gt;0] + RGB_YUV_TABLE[(b +  512)&gt;&gt;0]) &gt;&gt; 16)-128;
<a name="line683"></a>          UDU[pos] = ((RGB_YUV_TABLE[(r +  768)&gt;&gt;0] + RGB_YUV_TABLE[(g + 1024)&gt;&gt;0] + RGB_YUV_TABLE[(b + 1280)&gt;&gt;0]) &gt;&gt; 16)-128;
<a name="line684"></a>          VDU[pos] = ((RGB_YUV_TABLE[(r + 1280)&gt;&gt;0] + RGB_YUV_TABLE[(g + 1536)&gt;&gt;0] + RGB_YUV_TABLE[(b + 1792)&gt;&gt;0]) &gt;&gt; 16)-128;
<a name="line685"></a>
<a name="line686"></a>        }
<a name="line687"></a>
<a name="line688"></a>        _DCY = processDU(YDU, fdtbl_Y, _DCY, YDC_HT, YAC_HT);
<a name="line689"></a>        _DCU = processDU(UDU, fdtbl_UV, _DCU, UVDC_HT, UVAC_HT);
<a name="line690"></a>        _DCV = processDU(VDU, fdtbl_UV, _DCV, UVDC_HT, UVAC_HT);
<a name="line691"></a>        x+=32;
<a name="line692"></a>        }
<a name="line693"></a>        y+=8;
<a name="line694"></a>      }
<a name="line695"></a>
<a name="line696"></a>
<a name="line697"></a>      ////////////////////////////////////////////////////////////////
<a name="line698"></a>
<a name="line699"></a>      // Do the bit alignment of the EOI marker
<a name="line700"></a>      if ( bytepos &gt;= 0 ) {
<a name="line701"></a>        var fillbits = [];
<a name="line702"></a>        fillbits[1] = bytepos+1;
<a name="line703"></a>        fillbits[0] = (1&lt;&lt;(bytepos+1))-1;
<a name="line704"></a>        writeBits(fillbits);
<a name="line705"></a>      }
<a name="line706"></a>
<a name="line707"></a>      writeWord(0xFFD9); //EOI
<a name="line708"></a>
<a name="line709"></a>      var jpegDataUri = &#39;data:image/jpeg;base64,&#39;
<a name="line710"></a>        + goog.crypt.base64.encodeString(byteout.join(&#39;&#39;));
<a name="line711"></a>
<a name="line712"></a>      byteout = [];
<a name="line713"></a>
<a name="line714"></a>      return jpegDataUri
<a name="line715"></a>  }
<a name="line716"></a>
<a name="line717"></a>  function setQuality(quality){
<a name="line718"></a>    if (quality &lt;= 0) {
<a name="line719"></a>      quality = 1;
<a name="line720"></a>    }
<a name="line721"></a>    if (quality &gt; 100) {
<a name="line722"></a>      quality = 100;
<a name="line723"></a>    }
<a name="line724"></a>
<a name="line725"></a>    if(currentQuality == quality) return // don&#39;t recalc if unchanged
<a name="line726"></a>
<a name="line727"></a>    var sf = 0;
<a name="line728"></a>    if (quality &lt; 50) {
<a name="line729"></a>      sf = Math.floor(5000 / quality);
<a name="line730"></a>    } else {
<a name="line731"></a>      sf = Math.floor(200 - quality*2);
<a name="line732"></a>    }
<a name="line733"></a>
<a name="line734"></a>    initQuantTables(sf);
<a name="line735"></a>    currentQuality = quality;
<a name="line736"></a>  }
<a name="line737"></a>
<a name="line738"></a>  function init(){
<a name="line739"></a>    if(!opt_quality) opt_quality = 50;
<a name="line740"></a>    // Create tables
<a name="line741"></a>    initCharLookupTable()
<a name="line742"></a>    initHuffmanTbl();
<a name="line743"></a>    initCategoryNumber();
<a name="line744"></a>    initRGBYUVTable();
<a name="line745"></a>
<a name="line746"></a>    setQuality(opt_quality);
<a name="line747"></a>  }
<a name="line748"></a>
<a name="line749"></a>  init();
<a name="line750"></a>
<a name="line751"></a>};
</pre>


</body>
</html>
